/*==============================================
 * Task4: Camera test
 *
 * Written by <YOUR NAME HERE>
 *
 *==============================================*/
#pragma once

#include "SceneEngine.h"
#include "Node.h"
#include "GameUtils.h"
#include "Fail.h"

/** Labtask 4a: Testing LookAt function.
*/
class CTask4a: public CScene
{
public:
	void Enter();
	void Update(float dt);
	void Draw(float dt);
	void Leave();
protected:
	CXMesh* mpArrowMesh;
	CMeshNode mArrow;
	CXMesh* mpPlayerMesh;
	CMeshNode mPlayer;
	CXMesh* mpGroundMesh;
};

void CTask4a::Enter()
{
	mpGroundMesh=new CXMesh(GetDevice(),"media/checker.x");
	mpPlayerMesh=new CXMesh(GetDevice(),"media/teapot.x");
	mpArrowMesh=new CXMesh(GetDevice(),"media/arrow.x");

	// setup scene (inc camera & lights)
	SetupDefaultD3DOptions(GetDevice(),true);
	// overhead view
	CameraLookAt(GetDevice(),D3DXVECTOR3(0,10,-5),D3DXVECTOR3(0,1,0));

	// init
	mPlayer.Init(mpPlayerMesh,D3DXVECTOR3(0,0.5f,0));
	mArrow.Init(mpArrowMesh,D3DXVECTOR3(0,1,0));
}
void CTask4a::Update(float dt)
{
	// basic movement:
	const float SPEED=2.0f;
	const float TURN=D2R(60);
	D3DXVECTOR3 move;
	move=GetKeyboardVector(CURSOR_HPR_KEYS);	// get keyboard inupt
	mPlayer.Turn(move*dt*TURN);
	move=GetKeyboardVector(WSADRF_KEYS);	// get keyboard inupt
	mPlayer.Move(move*dt*SPEED);

	// helper, just in case the player gets lost:
	if (CGameWindow::KeyPress(VK_SPACE))
	{
		mPlayer.SetPos(0,0.5f,0);
		mPlayer.SetHpr(0,0,0);
	}

	// make the arrow look at the player:
	mArrow.LookAt(mPlayer);
}
void CTask4a::Draw(float dt)
{
    // Clear the backbuffer to a black color
    GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, BLUE_COL, 1.0f, 0 );
	GetDevice()->BeginScene();

	// draw the ground
	mpGroundMesh->Draw(D3DXVECTOR3(0,0,0));
	// draw the objects
	mPlayer.Draw();
	mArrow.Draw();

	GetDevice()->EndScene();
}
void CTask4a::Leave()
{
	SAFE_DELETE(mpGroundMesh);
	SAFE_DELETE(mpPlayerMesh);
	SAFE_DELETE(mpArrowMesh);
}

///////////////////////////////////////////////////////////////////
/** Labtask 4b: Camera LookAt function.
*/
class CTask4b: public CScene
{
public:
	void Enter();
	void Update(float dt);
	void Draw(float dt);
	void Leave();
protected:
	CCameraNode mCamera;
	CXMesh* mpArrowMesh;
	CMeshNode mArrow;
	CXMesh* mpPlayerMesh;
	CMeshNode mPlayer;
	CXMesh* mpGroundMesh;
};

void CTask4b::Enter()
{
	mpGroundMesh=new CXMesh(GetDevice(),"media/checker.x");
	mpPlayerMesh=new CXMesh(GetDevice(),"media/teapot.x");
	mpArrowMesh=new CXMesh(GetDevice(),"media/arrow.x");

	// setup scene (inc camera & lights)
	SetupDefaultD3DOptions(GetDevice(),true);

	// init
	mPlayer.Init(mpPlayerMesh,D3DXVECTOR3(0,0.5f,0));
	mArrow.Init(mpArrowMesh,D3DXVECTOR3(0,1,0));
}
void CTask4b::Update(float dt)
{
	// basic movement:
	const float SPEED=2.0f;
	const float TURN=D2R(60);
	D3DXVECTOR3 move;
	move=GetKeyboardVector(CURSOR_HPR_KEYS);	// get keyboard inupt
	mPlayer.Turn(move*dt*TURN);
	move=GetKeyboardVector(WSADRF_KEYS);	// get keyboard inupt
	mPlayer.Move(move*dt*SPEED);

	// helper, just in case the player gets lost:
	if (CGameWindow::KeyPress(VK_SPACE))
	{
		mPlayer.SetPos(0,0.5f,0);
		mPlayer.SetHpr(0,0,0);
	}
	// make the arrow look at the player:
	mArrow.LookAt(mPlayer);

	// put the camera above the arrow
	mCamera.SetPos(mArrow.GetPos()+D3DXVECTOR3(0,5,0));
	// make the camera look at player:
	mCamera.LookAt(mPlayer);

}
void CTask4b::Draw(float dt)
{
	// this is the important bit:
	// set the view/projection matrixes from the camera
	// not the default CameraLookAt() item
	mCamera.SetMatrixes(GetDevice());

	// Clear the backbuffer to a black color
    GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, BLUE_COL, 1.0f, 0 );
	GetDevice()->BeginScene();

	// draw the ground
	mpGroundMesh->Draw(D3DXVECTOR3(0,0,0));
	// draw the objects
	mPlayer.Draw();
	mArrow.Draw();

	GetDevice()->EndScene();
}
void CTask4b::Leave()
{
	SAFE_DELETE(mpGroundMesh);
	SAFE_DELETE(mpPlayerMesh);
	SAFE_DELETE(mpArrowMesh);
}

///////////////////////////////////////////////////////////////////
/** Labtask 4c: Camera modes.
*/
class CTask4c: public CScene
{
public:
	void Enter();
	void Update(float dt);
	void Draw(float dt);
	void Leave();
	void CameraMode();
protected:
	int mMode;
	CCameraNode mCamera;
	CXMesh* mpArrowMesh;
	CMeshNode mArrow;
	CXMesh* mpPlayerMesh;
	CMeshNode mPlayer;
	CXMesh* mpGroundMesh;
};

void CTask4c::Enter()
{
	mpGroundMesh=new CXMesh(GetDevice(),"media/checker.x");
	mpPlayerMesh=new CXMesh(GetDevice(),"media/teapot.x");
	mpArrowMesh=new CXMesh(GetDevice(),"media/arrow.x");

	// setup scene (inc camera & lights)
	SetupDefaultD3DOptions(GetDevice(),true);

	// init
	mPlayer.Init(mpPlayerMesh,D3DXVECTOR3(0,0.5f,0));
	mArrow.Init(mpArrowMesh,D3DXVECTOR3(0,1,0));

	mMode=4;
}
void CTask4c::Update(float dt)
{
	// basic movement:
	const float SPEED=2.0f;
	const float TURN=D2R(60);
	D3DXVECTOR3 move;
	move=GetKeyboardVector(CURSOR_HPR_KEYS);	// get keyboard inupt
	mPlayer.Turn(move*dt*TURN);
	move=GetKeyboardVector(WSADRF_KEYS);	// get keyboard inupt
	mPlayer.Move(move*dt*SPEED);

	// helper, just in case the player gets lost:
	if (CGameWindow::KeyPress(VK_SPACE))
	{
		mPlayer.SetPos(0,0.5f,0);
		mPlayer.SetHpr(0,0,0);
	}
	// make the arrow look at the player:
	mArrow.LookAt(mPlayer);

	// the camera stuff
	CameraMode();
}
void CTask4c::CameraMode()
{
	if (CGameWindow::KeyPress(VK_F1))		mMode=0;
	if (CGameWindow::KeyPress(VK_F2))		mMode=1;
	if (CGameWindow::KeyPress(VK_F3))		mMode=2;
	if (CGameWindow::KeyPress(VK_F4))		mMode=3;
	if (CGameWindow::KeyPress(VK_F5))		mMode=4;

	switch(mMode)
	{
	case 0:	// tracking
		GetEngine()->SetTitle("Tracking Camera");
		//TODO("set the camera's location");
		//TODO("make the camera look at the player");
		mCamera.SetPos(0.0f,10.0f,0.0f);
		mCamera.LookAt(mPlayer);
		break;
	case 1: // first person
		GetEngine()->SetTitle("First person");
		//TODO("set pos & hpr to match player");
		mCamera.mPos = mPlayer.mPos;
		mCamera.mHpr = mPlayer.mHpr;
		break;
	case 2: // plank third person
		GetEngine()->SetTitle("Plank third person");
        //TODO("Set the camera's position to be behind the player (5 units) & slightly up (3 units)");
		//TODO("make the camera look at the player");
		mCamera.SetPos(mPlayer.OffsetPos(D3DXVECTOR3(0,3,-5)));
		mCamera.LookAt(mPlayer);
		//mCamera.set
		break;
	case 3:
		GetEngine()->SetTitle("Fixed Overhead");
        //TODO("Set the camera's position to be above the player");
		//TODO("make the camera look at the player");
		mCamera.mPos.x = mPlayer.mPos.x;
		mCamera.mPos.y = mPlayer.mPos.y+15;
		mCamera.mPos.z = mPlayer.mPos.z;
		mCamera.LookAt(mPlayer);
		break;
	default:	// fixed:
		GetEngine()->SetTitle("Fixed Camera");
		mCamera.SetPos(0,10,-5);
		mCamera.LookAt(D3DXVECTOR3(0,1,0));
		break;
	}
}
void CTask4c::Draw(float dt)
{
	// this is the important bit:
	// set the view/projection matrixes from the camera
	// not the default CameraLookAt() item
	mCamera.SetMatrixes(GetDevice());

	// Clear the backbuffer to a black color
    GetDevice()->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, BLUE_COL, 1.0f, 0 );
	GetDevice()->BeginScene();

	// draw the ground
	mpGroundMesh->Draw(D3DXVECTOR3(0,0,0));
	// draw the objects
	mPlayer.Draw();
	mArrow.Draw();

	GetDevice()->EndScene();
}
void CTask4c::Leave()
{
	SAFE_DELETE(mpGroundMesh);
	SAFE_DELETE(mpPlayerMesh);
	SAFE_DELETE(mpArrowMesh);
}


int WINAPI WinMain(HINSTANCE hInstance, 
				   HINSTANCE hPrevInstance, 
				   LPTSTR lpCmdLine, int nCmdShow)
{
    ENABLE_LEAK_DETECTION();	// Enable run-time memory check for debug builds.
	CSceneEngine eng(640,480,false);
	eng.AddScene(new CTask4c);
	return eng.Go(hInstance);	// runs everything
}
